import logging

from django.db.models import Q
from django.shortcuts import render

# Create your views here.
from drf_yasg import openapi
from drf_yasg.utils import swagger_auto_schema
from rest_framework.decorators import action
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework import viewsets, status

from MSB_ERP.apps.erp_system.serializer.menu_serializer import MenuSerializer

logger=logging.getLogger('erp')
#功能菜单的模型类
    #1 新增  2 查询单个功能菜单 3 查询所有的菜单 4 查询某个父类菜单下面的所有子菜单列表 5 删除某一个功能菜单
    # 6 批量 7修改功能菜单,传参ids=[1,2,3]  8 查询所有的顶级菜单
from erp_system.models import MenuModel, PermissionsModel


class MenuView(viewsets.ModelViewSet):
    """
    create :
    新增菜单,

    参数：为Menu对象，其中delete_flag,create_time,update_time 不用传参 ,return ：添加之后的对象

    retrieve:
    查询当个菜单对象

    list:
    查询所有的菜单

    如果参数中有pid,则查询某一个父菜单的所有子菜单列表，pid=0是表示查询父菜单

    update:
    修改菜单

    partial_update:
    局部修改菜单，修改任意指定的属性

    destroy:
    删除指定的ID菜单

    get_menus_by_permission
    当前登录用户，根据权限查询那些拥有get权限的功能菜单列表(树形菜单二级)

    """
    queryset = MenuModel.objects.filter(delete_flag=0).all()
    serializer_class = MenuSerializer
    #认证之后可以拿到登录的用户,request.user
    #permission_classes = [IsAuthenticated]
    def get_queryset(self):
        #两种情况：1 查询所有菜单列表 不需要参数 2 查询某个父菜单下面的所有子菜单列表，需要参数，名字是pid，pid=0时，查询所有的顶级菜单
        query_param=self.request.query_params.get('pid',None)
        if query_param:
            pid=int(query_param)
            if pid==0: #查询所有的顶级菜单列表
                return MenuModel.objects.filter(parent__isnull=True,delete_flag=0).all()
            else: #查询某个父菜单下面的所有子菜单列表
                return MenuModel.objects.filter(parent__id=pid,delete_flag=0).all()
        else:
            return MenuModel.objects.filter(delete_flag=0).all()

    def destroy(self, request, *args, **kwargs):
        #修改一下删除的标记为：delete_flag=1
        menu=self.get_object()
        menu.delete_flag='1'
        menu.save()
        MenuModel.objects.filter(parent__id=menu.id).update(delete_flag=1)

        return Response(status=status.HTTP_204_NO_CONTENT)


    del_ids=openapi.Schema(type=openapi.TYPE_OBJECT,required=['ids'],properties={
        'ids':openapi.Schema(type=openapi.TYPE_ARRAY,items=openapi.Schema(type=openapi.TYPE_INTEGER),description="选择需要删除的ID（主键）列表")
        #TYPE_ARRAY是列表，items列表里的元素是整数类型
    })#TYPE_OBJECT传参是json格式,required参数名字,properties规定每个参数的具体类型

    #action装饰器可以接收两个参数：methods:该action对应的请求方式
    #detail:声明该action是否与单一资源对应，是否是xxx/<pk>/方法名
    #True表示路径是xxx/<pk>/方法名
    #False表示路径是xxx/方法名
    @swagger_auto_schema(method='delete',request_body=del_ids,operation_description="批量删除") #在接口注释,request_body传参,在接口文档里添加multiple_delete函数
    @action(methods=['delete'],detail=False)
    def multiple_delete(self, request, *args, **kwargs):
        delete_ids=request.data.get('ids')
        if not delete_ids:
            return Response(data={'detail':'参数错误，ids是必传参数'},status=status.HTTP_400_BAD_REQUEST)
        elif not isinstance(delete_ids,list):#判断类型
            return Response(data={'detail': '格式错误，要list'}, status=status.HTTP_400_BAD_REQUEST)

        #先删除传递过来的菜单
        MenuModel.objects.filter(id__in=delete_ids).update(delete_flag=1)
        #删除所有的子菜单

        MenuModel.objects.filter(parent__id__in=delete_ids).update(delete_flag=1)
        return Response(status=status.HTTP_204_NO_CONTENT)

    @action(methods=['get'], detail=False)
    def get_menus_by_permission(self,request,*args,**kwargs):
        #当前登录用户，根据权限查询那些拥有get权限的功能菜单列表

        #第一步查询当前登录用户拥有的权限ID列表,values_list返回列表，values返回字典（字段名为key）
        permission_ids= request.user.roles.values_list('permissions',flat=True).distinct()

        #第二部查询拥有get权限的功能菜单的ID列表,两个filter是并且的关系,Q查询条件
        #注意：父菜单没有任何method,所以如果是父菜单的权限也应该要出现
        menu_ids=PermissionsModel.objects.filter(id__in=permission_ids)\
            .filter(Q(method='GET') | Q(is_menu=True)).values_list('menu',flat=True)

        #第三步：根据ID查询菜单列表,列表里面是对象
        menu_list=MenuModel.objects.filter(id__in=menu_ids,delete_flag=0).all()
        serializer=MenuSerializer(instance=menu_list,many=True)
        #通过serializer把对象变成字典
        #变成一个树形结构
        tree_dict={} #代表一个父菜单
        tree_data=[]

        for item in serializer.data:
            tree_dict[item['id']]=item
        for i in tree_dict:
            if tree_dict[i]['parent']:
                pid=tree_dict[i]['parent']#拿到父菜单的key
                parent=tree_dict[pid]
                parent.setdefault('children',[]).append(tree_dict[i])
            else: #是否父菜单
                tree_data.append(tree_dict[i])

        return Response(tree_data)












